package org.cybzacg.convert.exception;


import org.cybzacg.convert.enums.ConversionError;

import java.io.Serial;

/**
 * 类型转换异常类
 * 统一处理类型转换过程中的异常情况
 *
 * @author cybzacg.blog
 * @version 3.0
 * @since 3.0
 */
public class ConversionException extends AbstractConversionException {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 构造方法
     *
     * @param errorType 错误类型
     * @param message 异常消息
     */
    public ConversionException(ConversionError errorType, String message) {
        super(errorType, message, null, null, null, null);
    }

    /**
     * 构造方法
     *
     * @param errorType 错误类型
     * @param message 异常消息
     * @param cause 原因异常
     */
    public ConversionException(ConversionError errorType, String message, Throwable cause) {
        super(errorType, message, cause, null, null, null);
    }

    /**
     * 构造方法
     *
     * @param message 异常消息
     */
    public ConversionException(String message) {
        this(ConversionError.UNKNOWN_ERROR, message);
    }

    /**
     * 构造方法
     *
     * @param message 异常消息
     * @param cause 原因异常
     */
    public ConversionException(String message, Throwable cause) {
        this(ConversionError.UNKNOWN_ERROR, message, cause);
    }

    /**
     * 构造方法
     *
     * @param sourceType 源类型
     * @param targetType 目标类型
     * @param sourceValue 源值
     */
    public ConversionException(Class<?> sourceType, Class<?> targetType, Object sourceValue) {
        super(ConversionError.TYPE_MISMATCH,
              String.format("类型转换失败: %s -> %s, 源值: %s",
                           sourceType != null ? sourceType.getSimpleName() : "null",
                           targetType != null ? targetType.getSimpleName() : "null",
                           sourceValue),
              null, sourceType, targetType, sourceValue);
    }

    /**
     * 构造方法
     *
     * @param sourceType 源类型
     * @param targetType 目标类型
     * @param sourceValue 源值
     * @param cause 原因异常
     */
    public ConversionException(Class<?> sourceType, Class<?> targetType, Object sourceValue, Throwable cause) {
        super(ConversionError.TYPE_MISMATCH,
              String.format("类型转换失败: %s -> %s, 源值: %s",
                           sourceType != null ? sourceType.getSimpleName() : "null",
                           targetType != null ? targetType.getSimpleName() : "null",
                           sourceValue),
              cause, sourceType, targetType, sourceValue);
    }


    /**
     * 创建类型不匹配异常
     *
     * @param sourceType 源类型
     * @param targetType 目标类型
     * @param sourceValue 源值
     * @return 异常实例
     */
    public static ConversionException typeMismatch(Class<?> sourceType, Class<?> targetType, Object sourceValue) {
        return new ConversionException(sourceType, targetType, sourceValue,
                new IllegalArgumentException("类型不匹配，无法进行转换"));
    }

    /**
     * 创建空值异常
     *
     * @param targetType 目标类型
     * @return 异常实例
     */
    public static ConversionException nullValue(Class<?> targetType) {
        return new ConversionException(null, targetType, null,
                new IllegalArgumentException("源值为null，且目标类型不允许null"));
    }

    /**
     * 创建格式异常
     *
     * @param sourceType 源类型
     * @param targetType 目标类型
     * @param sourceValue 源值
     * @param format 期望的格式
     * @return 异常实例
     */
    public static ConversionException formatError(Class<?> sourceType, Class<?> targetType, Object sourceValue, String format) {
        String message = String.format("格式错误，期望格式: %s", format);
        return new ConversionException(sourceType, targetType, sourceValue,
                new IllegalArgumentException(message));
    }

    /**
     * 创建转换器未找到异常
     *
     * @param targetType 目标类型
     * @return 异常实例
     */
    public static ConversionException converterNotFound(Class<?> targetType) {
        String message = String.format("未找到支持类型 %s 的转换器", targetType.getSimpleName());
        return new ConversionException(message);
    }

    /**
     * 创建转换失败异常
     *
     * @param sourceType 源类型
     * @param targetType 目标类型
     * @param sourceValue 源值
     * @param cause 原因异常
     * @return 异常实例
     */
    public static ConversionException conversionFailed(Class<?> sourceType, Class<?> targetType, Object sourceValue, Throwable cause) {
        return new ConversionException(sourceType, targetType, sourceValue, cause);
    }
}
